package main.components;

import main.FactageSmet;
import main.MainFrame;
import main.MsSQLConnect;
import main.objects.TreeTitulNode;
import main.objects.XMLSmet;
import org.jdom2.JDOMException;

import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.EventObject;

public class TreeTitul extends JTree {

    private JPopupMenu contextMenu;
    private JMenuItem addSmetItem, addNodeItem, removeNodeItem;
    private JDialog addNodeDialog;
    private JTextField fieldNameNode, fieldCodeNode;

    public DefaultTreeModel treeModel;
    private TreeSmet treeSmet;
    private Date dateChange;

    //region Основные поля класса
    private TreeTitulNode ROOT_NODE, CURRENT_NODE;
    //endregion

    //region Конструктор
    public TreeTitul(TreeTitulNode root, TreeSmet treeSmet) {

        this.ROOT_NODE = root;
        this.treeSmet = treeSmet;

        final DefaultTreeCellEditor editor = new MyTreeCellEditor(this,
                (DefaultTreeCellRenderer) getCellRenderer());
        setCellEditor(editor);

        editor.addCellEditorListener(new CellEditorListener() {
            @Override
            public void editingStopped(ChangeEvent changeEvent) {

                TreeTitulNode editNode = (TreeTitulNode) getLastSelectedPathComponent();

                String newValue = editor.getCellEditorValue().toString();

                if (!newValue.equals("") && !newValue.equals(editNode.getName())) editNode.updateName(newValue);

                if (editNode.isEPS) setCurNode();

            }

            @Override
            public void editingCanceled(ChangeEvent changeEvent) {

            }
        });

        initTree();

    }
    //endregion

    //region Инициализация дерева
    private void initTree() {

        treeModel = new DefaultTreeModel(ROOT_NODE);
        setModel(treeModel);
        setEditable(true);
        setCellRenderer(new MyTreeRenderer());

        //region Контекстное меню
        contextMenu = new JPopupMenu();
        contextMenu.setPreferredSize(new Dimension(250, 110));

        addNodeItem = new JMenuItem("Добавить EPS");
        addNodeItem.setIcon(new ImageIcon(getClass().getResource("icons/add12x12.png")));
        addNodeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0));
        addNodeItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                addTitulNode();
            }
        });

        removeNodeItem = new JMenuItem("Удалить EPS");
        removeNodeItem.setIcon(new ImageIcon(getClass().getResource("icons/delete12x12.png")));
        removeNodeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
        removeNodeItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                removeNodeDialogShow();
            }
        });

        addSmetItem = new JMenuItem("Добавить смету - XML");
        addSmetItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                addXMLSmet();
            }
        });

        contextMenu.add(addNodeItem);
        contextMenu.add(removeNodeItem);
        contextMenu.add(new JSeparator());
        contextMenu.add(addSmetItem);
        //endregion

        //region Слушатели
        addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
                setCurNode();
            }
        });

        addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent keyEvent) {

            }

            @Override
            public void keyPressed(KeyEvent keyEvent) {
                if (keyEvent.getKeyCode() == KeyEvent.VK_INSERT) {
                    addTitulNode();
                } else if (keyEvent.getKeyCode() == KeyEvent.VK_DELETE) {
                    removeNodeDialogShow();
                }
            }

            @Override
            public void keyReleased(KeyEvent keyEvent) {

            }
        });

        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent mouseEvent) {

                if (mouseEvent.getButton() == 3) {
                    popupMenuOpen(mouseEvent.getX(), mouseEvent.getY());
                } else if (mouseEvent.getButton() == 1) {
                    setCurNode();
                }
            }
        });
        //endregion

    }
    //endregion

    //region Проверка выбранного текущего узла
    private void setCurNode() {

        CURRENT_NODE = null;
        CURRENT_NODE = (TreeTitulNode) this.getLastSelectedPathComponent();
        if (CURRENT_NODE == null) return;

        MainFrame.tbBtnAdd.setEnabled(true);
        MainFrame.tbBtnAdd.setToolTipText(CURRENT_NODE.equals(ROOT_NODE) ? "Добавить титул объекта (Ins)" : "Добавить EPS (Ins)");
        MainFrame.tbBtnRename.setToolTipText(CURRENT_NODE.isTitul ? "Переименовать титул объекта (F2)" : "Переименовать EPS (F2)");
        MainFrame.tbBtnDelete.setToolTipText(CURRENT_NODE.isTitul ? "Удалить титул объекта (Del)" : "Удалить EPS (Del)");
        MainFrame.tbBtnRename.setEnabled(!CURRENT_NODE.equals(ROOT_NODE));
        MainFrame.tbBtnDelete.setEnabled(!CURRENT_NODE.equals(ROOT_NODE));
        MainFrame.tbBtnImport.setEnabled(!CURRENT_NODE.equals(ROOT_NODE) && CURRENT_NODE.isTitul);

        if (CURRENT_NODE.isEPS) treeSmet.showSmet(CURRENT_NODE);
        MainFrame.SELECTED_EPS = CURRENT_NODE;
        MainFrame.CURRENT_TITUL = MainFrame.ALL_EPS.get(CURRENT_NODE.getTitulId() + "-titul");

    }
    //endregion

    public void addTitulNode() {

        TreeTitulNode newNode = null;

        if (CURRENT_NODE == null) return;

        try {

            FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

            if (CURRENT_NODE.getId() == 0) {
                Statement stat = FactageSmet.IMPORT_FACTAGE_CONNECTION.createStatement();
                stat.executeUpdate("INSERT INTO Titul VALUES ('Новый Титул', '')", Statement.RETURN_GENERATED_KEYS);
                ResultSet rs = stat.getGeneratedKeys();

                if (rs.next()){
                    newNode = new TreeTitulNode(
                            "Новый Титул",
                            rs.getInt(1),
                            "");

                    MainFrame.ALL_EPS.put((String) newNode.getUserObject(), newNode);
                    ((DefaultTreeModel) getModel()).insertNodeInto(newNode, CURRENT_NODE, CURRENT_NODE.getChildCount());
                }
                rs.close();
                stat.close();

            } else {

                int parentIdN;
                int titulIdN;
                if (CURRENT_NODE.getTitulId() == 0) {

                    parentIdN = 0;
                    titulIdN = CURRENT_NODE.getId();

                } else {

                    parentIdN = CURRENT_NODE.getId();
                    titulIdN = CURRENT_NODE.getTitulId();

                }

                Statement stat = FactageSmet.IMPORT_FACTAGE_CONNECTION.createStatement();
                stat.executeUpdate("INSERT INTO EPS VALUES ('Новый Раздел', '', " + parentIdN + ", " + titulIdN + ")", Statement.RETURN_GENERATED_KEYS);
                ResultSet rs = stat.getGeneratedKeys();

                if (rs.next()){
                    newNode = new TreeTitulNode(
                            "Новый Раздел",
                            rs.getInt(1),
                            parentIdN,
                            titulIdN,
                            "");

                    MainFrame.ALL_EPS.put((String) newNode.getUserObject(), newNode);
                    ((DefaultTreeModel) getModel()).insertNodeInto(newNode, CURRENT_NODE, CURRENT_NODE.getChildCount());
                }

                rs.close();
                stat.close();

            }

            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        if (newNode != null) {

            expandPath(new TreePath(newNode.getPath()));
            setSelectionRow(getRowForPath(new TreePath(newNode.getPath())));
            startEditingAtPath(new TreePath(newNode.getPath()));

        } else System.out.println("something goes wrong");

    }

    public void renameTitulNode() {

        CURRENT_NODE = (TreeTitulNode) this.getLastSelectedPathComponent();

        if (CURRENT_NODE == null) return;
        startEditingAtPath(new TreePath(CURRENT_NODE.getPath()));

    }

    //region popupMenuOpen(int X, int Y) - отображение всплывающего меню
    private void popupMenuOpen(int X, int Y) {

        addSmetItem.setEnabled(false);
        removeNodeItem.setEnabled(false);

        addNodeItem.setText("Добавить титул");
        removeNodeItem.setText("Удалить титул");

        MainFrame.SELECTED_EPS = null;

        CURRENT_NODE = (TreeTitulNode) this.getLastSelectedPathComponent();

        if (CURRENT_NODE != null) {
            contextMenu.show(this, X, Y);

            if (!CURRENT_NODE.equals(ROOT_NODE)) {

                if (CURRENT_NODE.isEPS) {
                    addSmetItem.setEnabled(true);
                    MainFrame.SELECTED_EPS = CURRENT_NODE;
                    MainFrame.CURRENT_TITUL = MainFrame.ALL_EPS.get(CURRENT_NODE.getTitulId() + "-titul");
                }

                removeNodeItem.setEnabled(true);

                addNodeItem.setText("Добавить EPS");
                removeNodeItem.setText(CURRENT_NODE.isTitul ? "Удалить титул" : "Удалить EPS");
            }
        }
    }
    //endregion)

    public void removeNodeDialogShow() {

        if (CURRENT_NODE == null || CURRENT_NODE == ROOT_NODE) return;

        int dialogButton = JOptionPane.YES_NO_OPTION;
        int dialogResult = JOptionPane.showConfirmDialog (null, "Вы действительно хотите удалить узел?","Удаление", dialogButton);
        if (dialogResult == JOptionPane.YES_OPTION) {
            try {
                FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

                Statement stat = FactageSmet.IMPORT_FACTAGE_CONNECTION.createStatement();

                if (MainFrame.ALL_EPS.containsKey(CURRENT_NODE.getUserObject().toString())) MainFrame.ALL_EPS.remove(CURRENT_NODE.getUserObject().toString());

                if (CURRENT_NODE.isTitul) {
                    stat.executeUpdate("DELETE FROM Titul WHERE id = " + CURRENT_NODE.getId());
                } else {
                    stat.executeUpdate("DELETE FROM EPS WHERE id = " + CURRENT_NODE.getId());
                }

                ((DefaultTreeModel) getModel()).removeNodeFromParent(CURRENT_NODE);

                FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //region chooseFile() - диалог выбора файла для открытия смет
    private File[] chooseFile(String fType) {

        File[] files = new File[0];
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("Выберите файл сметы");

        if (fType.equals("arps")) {
            FileFilter fileFilter = new FileNameExtensionFilter("АРПС-сметы 1.10", "arp");
            fileChooser.setFileFilter(fileFilter);
            fileChooser.setMultiSelectionEnabled(true);
        } else {
            FileFilter fileFilter = new FileNameExtensionFilter("XML-сметы", "xml");
            fileChooser.setFileFilter(fileFilter);
            fileChooser.setMultiSelectionEnabled(true);
        }

        String homeDir = new File("").getAbsolutePath();
        fileChooser.setCurrentDirectory(new File(homeDir));
        fileChooser.setApproveButtonText("Открыть");

        if (fileChooser.showDialog(null, "Открыть") == JFileChooser.APPROVE_OPTION) {
            files = fileChooser.getSelectedFiles();
        }
        return files;
    }
    //endregion

    private void addXMLSmet() {

        File[] XMLFiles = chooseFile("xml");

        if (XMLFiles.length < 1) return;

        for (File xmlFile : XMLFiles) {

            try {
                new XMLSmet(xmlFile);
            } catch (IOException | JDOMException e) {
                e.printStackTrace();
            }

        }


    }

    //region Геттеры
    public TreeTitulNode getRoot() {
        return ROOT_NODE;
    }

    public JTree getTree() {
        return this;
    }
    //endregion

}

class MyTreeCellEditor extends DefaultTreeCellEditor {

    public MyTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
        super(tree, renderer);
    }

    @Override
    public Component getTreeCellEditorComponent(JTree tree, Object value,
                                                boolean isSelected, boolean expanded, boolean leaf, int row) {

        return super.getTreeCellEditorComponent(tree, value, isSelected, expanded,
                leaf, row);
    }

    @Override
    public boolean isCellEditable(EventObject e) {

        TreeTitulNode CURRENT_NODE;

        if (lastPath == null ) return false;

        CURRENT_NODE = (TreeTitulNode) MainFrame.treeTitul.getLastSelectedPathComponent();

        return super.isCellEditable(e) && !MainFrame.treeTitul.treeModel.getRoot().equals(CURRENT_NODE);
    }
}

class MyTreeRenderer extends DefaultTreeCellRenderer {

    public MyTreeRenderer() {}

    public Component getTreeCellRendererComponent(
            JTree tree,
            Object value,
            boolean sel,
            boolean expanded,
            boolean leaf,
            int row,
            boolean hasFocus) {

        super.getTreeCellRendererComponent(
                tree, value, sel,
                expanded, leaf, row,
                hasFocus);

        TreeTitulNode selNode = (TreeTitulNode) value;

        if (selNode.equals(MainFrame.treeTitul.getRoot())) {
            setIcon(new ImageIcon(getClass().getResource("root.gif")));
        } else if (selNode.isTitul) {
            setIcon(new ImageIcon(getClass().getResource("titul.gif")));
        } else {
            setIcon(getDefaultOpenIcon());
        }

        return this;
    }
}
